---------------------------------------------------------------
-- @Description：         叫分逻辑
---------------------------------------------------------------
local skynet = require "skynet"
local uu = require "sky_utils"
local log = require "sky_log"
local gg = require "game_utils"
local serpent = require "serpent"

local M = {
    --手牌点数得分后台配置
    analyze_card_t = nil,
    --数值1后台配置
    analyze_callscore_t_1 = nil,
    --数值2，3，4没有走配置，直接写到文件里
    analyze_callscore_t_2 = {
        [0] = { 0, 13.625 },
        [7] = { 13.625, 17.8 },
        [8] = { 17.8, 21.475 },
        [9] = { 21.475, 24.15 },
        [10] = { 24.15, 26.825 },
        [11] = { 26.825, 29.5},
        [12] = { 1000, 2000 },
        [13] = { 2000, 3001 },
    },
    analyze_callscore_t_3 = {
        [0] = { 0, 11.625 },
        [7] = { 11.625, 16.8 },
        [8] = { 16.8, 21.475 },
        [9] = { 21.475, 24.15 },
        [10] = { 24.15, 26.825 },
        [11] = { 26.825, 29.5},
        [12] = { 1000, 2000 },
        [13] = { 2000, 3001 },
    },
    analyze_callscore_t_4 = {
        [0] = { 0, 11.625 },
        [7] = { 11.625, 15.3 },
        [8] = { 15.3, 18.975 },
        [9] = { 18.975, 21.65 },
        [10] = { 21.65, 24.325 },
        [11] = { 24.325, 27},
        [12] = { 1000, 2000 },
        [13] = { 2000, 3001 },
    },
}

--============================= Local Function =============================--
local function read_config(plat_id)
    if not plat_id then
        plat_id = 124
    end

    local backstage_config_call_score
    local file = io.open(("./config/backstage_config_call_score_"..plat_id..".lua"), "r")
    if file then
        backstage_config_call_score = require ("backstage_config_call_score_"..plat_id)
    else
        backstage_config_call_score = require "backstage_config_call_score_124"
        log.error("read_config error!", "backstage_config_call_score_"..plat_id.." not exist!")
    end

    --牌分值数据
    local analyze_card_t = {}
    --叫分概率表
    local analyze_callscore_t = {}

    local card_str
    local score_str
    for i=0, 14 do
        card_str = backstage_config_call_score["card"..i]
        score_str = backstage_config_call_score["call_"..i]
        if card_str then 
            analyze_card_t[i] = {}
            for v in string.gmatch (card_str, "[^,]+") do
                --[1]是定花色分值 [2]是副牌分值 [3]是主牌分值
                table.insert(analyze_card_t[i], tonumber(v))
            end
        end

        if score_str then 
            analyze_callscore_t[i] = {}
            for v in string.gmatch (score_str, "[^,]+") do
                --(a,b] [1]是a,[2]是b 
                table.insert(analyze_callscore_t[i], tonumber(v))
            end
        end
    end

    M.analyze_card_t = analyze_card_t
    M.analyze_callscore_t_1 = analyze_callscore_t

    --log.info(" M.analyze_card_t=",  M.analyze_card_t)
    --log.info(" M.analyze_callscore_t_1=",  M.analyze_callscore_t_1)
end

--叫分时的分值计算
--开牌之后机器人对手牌进行分值排列: 4个花色中，得分最高的花色定为主花色
local function calc_main_color(handcards, platid)
    read_config(platid)

    local value, color, add_score, add_score_reset, add_score_reset_main
    local score_t = {}
    for i=1, 4 do
        score_t[i] = {}
        score_t[i].total_score = 0
        score_t[i].card_counts = 0
        score_t[i].color = i
        score_t[i].reset_total_score = 0        --定花色后的副牌分
        score_t[i].reset_total_score_main = 0   --定花色后的主牌分
    end

    for _, v in pairs(handcards) do
        value = uu.calc_card_value(v)
        color = uu.calc_card_color(v)

        add_score = (M.analyze_card_t[value] or {})[1] or 0
        if not score_t[color][add_score] then
            score_t[color][add_score] = {}
        end
        table.insert(score_t[color][add_score], v)
        score_t[color].card_counts = score_t[color].card_counts + 1
        score_t[color].total_score = score_t[color].total_score + add_score

        --在这个for循环里把 定花色后的  主牌副牌分值一起计算了
        add_score_reset = (M.analyze_card_t[value] or {})[2] or 0
        score_t[color].reset_total_score = score_t[color].reset_total_score + add_score_reset

        add_score_reset_main = (M.analyze_card_t[value] or {})[3] or 0
        score_t[color].reset_total_score_main = score_t[color].reset_total_score_main + add_score_reset_main
    end

    table.sort(score_t, function (a, b)
        return a.total_score > b.total_score
    end)

    return score_t
end

--定了主花色之后，用新的分数赋值
local function reset_card_score(score_t)
    
    for index, v in ipairs(score_t) do
        if index==1 then 
            v.total_score_new = v.reset_total_score_main
        else
            v.total_score_new = v.reset_total_score
        end
    end

    return score_t
end

--第1位叫分
local function call_score_pos_1(call_score_t, seat_info)
    local config_index

    local friend_seat = uu.get_friend_seatid(seat_info.m_seatid)
    local is_real_player = seat_info.detail[friend_seat].is_real_player
    --队友是机器人用数值2，真人则用数值1
    if is_real_player==1 then
        config_index = 1
    else
        config_index = 2
    end

    return config_index
end

--第2位叫分
local function call_score_pos_2(call_score_t, seat_info)
    local config_index 

    local first_call_player = call_score_t[1]
    local friend_seat = uu.get_friend_seatid(seat_info.m_seatid)
    local is_real_player = seat_info.detail[friend_seat].is_real_player
    local is_first_real_player = seat_info.detail[first_call_player.seatid].is_real_player
   
    --第1位玩家没有叫分：队友为机器人用数值2, 队友为真人 50%数值1 50%数值4  
    if first_call_player.type==1 then
        if is_real_player==1 then 
            local index = math.random(1, 100)
            if index<50 then
                config_index = 1
            else
                config_index = 4
            end
        else
            config_index = 2
        end
    else
        --第1位玩家叫分,且是真人，用3
        if is_first_real_player==1 then
            config_index = 3
        else
        --第1位玩家叫分,且是机器人
            if is_real_player then
                --队友是真人，用3
                config_index = 3
            else
                --队友是机器人，50%-2， 30%-3， 20%-4
                local index = math.random(1, 100)
                if index<50 then
                    config_index = 1
                elseif (index>=50 and index<80) then
                    config_index = 3
                else
                    config_index = 4
                end
            end
        end
    end

    return config_index
end

--第3位叫分
local function call_score_pos_3(call_score_t, seat_info)
    local config_index 

    local friend_seat = uu.get_friend_seatid(seat_info.m_seatid)
    local is_friend_real_player = seat_info.detail[friend_seat].is_real_player

    --前面叫分最大的座位号
    local seat_id, max_value 
    for _, v in pairs(call_score_t) do
        if v.score~=0 then
            if not max_value
            or max_value<v.score then 
                max_value = v.score
                seat_id = v.seatid
            end
        end
    end

    --没有叫分的玩家，队友是机器人，则用2； 队友是真人则50%-1；50%-4
    if seat_id then
        if is_friend_real_player then
            local index = math.random(1, 100)
            if index<50 then
                config_index = 1
            else
                config_index = 4
            end
        else
            config_index = 2
        end
    else
        --有叫分玩家
        --是队友
        if friend_seat==seat_id then
            --队友是机器人： 用2; 是真人：50%-1  50%-4 
            if is_friend_real_player then
                local index = math.random(1, 100)
                if index<50 then
                    config_index = 1
                else
                    config_index = 4
                end
            else
                config_index = 2
            end
        else
            --是对手
            --队友是机器人： 用3; 是真人：50%-2；30%-3; 20%-4
            if is_friend_real_player then
                local index = math.random(1, 100)
                if index<50 then
                    config_index = 2
                elseif (index>=50 and index<80) then
                    config_index = 3
                else
                    config_index = 4
                end
            else
                config_index = 3
            end
        end
    end

    return config_index
end

--第4位叫分
local function call_score_pos_4(call_score_t, seat_info)
    local config_index 

    local friend_seat = uu.get_friend_seatid(seat_info.m_seatid)
    local is_friend_real_player = seat_info.detail[friend_seat].is_real_player

    --前面叫分最大的座位号
    local seat_id, max_value 
    for _, v in pairs(call_score_t) do
        if v.score~=0 then
            if not max_value
            or max_value<v.score then 
                max_value = v.score
                seat_id = v.seatid
            end
        end
    end

    --没有叫分的玩家，队友是机器人，则用1； 队友是真人则50%-2；30%-3; 20%-4
    if seat_id then
        if is_friend_real_player then
            local index = math.random(1, 100)
            if index<50 then
                config_index = 2
            elseif (index>=50 and index<80) then
                config_index = 3
            else
                config_index = 4
            end
        else
            config_index = 1
        end
    else
        --有叫分玩家
        --是队友
        if friend_seat==seat_id then
            --队友是机器人： 用2; 是真人：50%-2；30%-3; 20%-4 
            if is_friend_real_player then
                local index = math.random(1, 100)
                if index<50 then
                    config_index = 2
                elseif (index>=50 and index<80) then
                    config_index = 3
                else
                    config_index = 4
                end
            else
                config_index = 2
            end
        else
            --是对手
            --队友是机器人： 用3; 是真人：50%-2；30%-3; 20%-4
            if is_friend_real_player then
                local index = math.random(1, 100)
                if index<50 then
                    config_index = 2
                elseif (index>=50 and index<80) then
                    config_index = 3
                else
                    config_index = 4
                end
            else
                config_index = 3
            end
        end
    end

    return config_index
end

--检测是否需要是重复叫分
local function check_is_repeat_call(call_score_t, seat_info)
    local m_seatid = seat_info.m_seatid

    for _, v in pairs(call_score_t) do
        if v.seatid==m_seatid then
            return true
        end
    end

    return false
end

--重复叫分
local function repeat_call_score(call_score_t, seat_info)
    local friend_seat = uu.get_friend_seatid(seat_info.m_seatid)
    local is_friend_real_player = seat_info.detail[friend_seat].is_real_player

    --前面叫分最大的座位号
    local seat_id, max_value 
    for _, v in pairs(call_score_t) do
        if v.score~=0 then
            if not max_value
            or max_value<v.score then 
                max_value = v.score
                seat_id = v.seatid
            end
        end
    end

    --叫分最大的是队友
    if not seat_id then
        log.error("repeat_call_score error no seat_id")
        return 1
    end

    local config_index, flag
    --叫分最大的是队友
    if seat_id==friend_seat then
        --队友是真人：50%-2；30%-3; 20%-4
        if is_friend_real_player then
            local index = math.random(1, 100)
            if index<50 then
                uu.debug_logic(1)
                config_index = 2
            elseif (index>=50 and index<80) then
                uu.debug_logic(2)
                config_index = 3
            else
                uu.debug_logic(3)
                config_index = 4
            end
            flag = 1
        else
            uu.debug_logic(4)
            --机器人则pass
            config_index = 0    --这里的0代表pass，外面会直接return
        end
    else
        --是对手
        --队友是真人：50%-2；30%-3; 20%-4
        if is_friend_real_player then
            local index = math.random(1, 100)
            if index<50 then
                uu.debug_logic(5)
                config_index = 2
            elseif (index>=50 and index<80) then
                uu.debug_logic(6)
                config_index = 3
            else
                uu.debug_logic(7)
               config_index = 4
            end
            flag = 2
        else
            --队友是机器人：50%-2；30%-3; 20%-4 [和真人是一样的，但是怕策划改所以写出来比较好]
            local index = math.random(1, 100)
            if index<50 then
                uu.debug_logic(8)
                config_index = 2
            elseif (index>=50 and index<80) then
                uu.debug_logic(9)
                config_index = 3
            else
                uu.debug_logic(10)
                config_index = 4
            end
            flag = 3
        end
    end

    return config_index, flag
end

--1真人3机器人用特殊规则
local function spec_call_score(pos, call_score_t, seat_info)
    uu.debug_logic("spec_call_score!")
    --log.info("spec_call_score pos=", pos)
    --log.info("spec_call_score call_score_t=", call_score_t)
    --log.info("spec_call_score seat_info=", seat_info)

    local config_index 

    if pos==1 then
        config_index = call_score_pos_1(call_score_t, seat_info)
    elseif pos==2 then
        config_index = call_score_pos_2(call_score_t, seat_info)
    elseif pos==3 then
        config_index = call_score_pos_3(call_score_t, seat_info)
    elseif pos==4 then
        config_index = call_score_pos_4(call_score_t, seat_info)
    end

    if not config_index then 
        log.error("spec_call_score error! pos=", pos)
    end

    return config_index or 1
end

--检测是否1真人3机器人
local function check_is_three_robot(seat_info)
    local real_player_count = 0
    for _, v in pairs(seat_info.detail) do
        if v.is_real_player==1 then 
            real_player_count = real_player_count + 1
        end
    end

    if real_player_count == 1 then
        return true
    end

    return false
end

--根据配置表得到叫分值
local function get_call_score_by_config(total_card_score, config_t)
    local call_score = 0

    for k, v in pairs(config_t) do
        if total_card_score > v[1] 
        and total_card_score <= v[2] then
            call_score = k
        end
    end

    return call_score
end

--是否需要叫13分
local function check_need_call_13(score_t)
    for _, v in pairs(score_t) do
        if tonumber(v.card_counts)>=10 then 
            return 13
        end
    end

    return 0
end

--检测这次叫的分是否有和之前分数一样，一样就不叫了
local function check_is_repeat_score(call_score, call_score_t)
    for _, v in pairs(call_score_t) do
        if (call_score~=0 and call_score<=v.score) then
            --log.info("call_score=", call_score)
            --log.info("call_score_t=", call_score_t)
            --log.info("v.score=", v.score)
            return true
        end
    end

    return false
end

--根据手牌得分换算配置表里的叫几分
local function get_call_score_value(score_t, pos, call_score_t, seat_info)
    local all_color_score = 0
    for _, v in pairs(score_t) do
        all_color_score = all_color_score + tonumber(v.total_score_new)
    end
    
    local call_score = 0
    local config_index = 1
    local config_t 

    call_score = check_need_call_13(score_t)
    if call_score~=0 then
        log.debug("get_call_score_value call_score[13]:", " tid="..(seat_info.tid or "nil").."| seat_id="..(seat_info.m_seatid or "nil")
            ..("| pos="..pos).."| call_score="..(call_score or "nil").."|"
            ..(config_index or "nil").."|"..(all_color_score or "nil").."|"..( score_t[1].color or "nil")
        )
        return call_score, config_index, all_color_score, score_t[1].color
    end

    --除了1真人3机器人特殊情况外，都使用默认叫分配置即可
    local repeat_flag
    if check_is_three_robot(seat_info) then 
        if check_is_repeat_call(call_score_t, seat_info) then
            config_index, repeat_flag = repeat_call_score(call_score_t, seat_info)
            if config_index==0 then
                log.debug("repeat_call_score:", " tid="..(seat_info.tid or "nil").."| seat_id="..(seat_info.m_seatid or "nil")
                    .."| user_id="..(seat_info.m_userid or "nil")..("| pos="..pos).."| call_score="..(0 or "nil").."|"
                    ..(0 or "nil").."|"..(all_color_score or "nil").."|"..( score_t[1].color or "nil")
                )
                return 0, 0, all_color_score, score_t[1].color
            end 
        else
            config_index = spec_call_score(pos, call_score_t, seat_info)
        end
    end
    config_t = M["analyze_callscore_t_"..config_index]

    call_score = get_call_score_by_config(tonumber(all_color_score), config_t)

    --实在不好写了，返回个标志位：1代表不超过10分 2代表不超过9分 3代表不超过10分
    if repeat_flag==1 then
        if call_score>10 then
            call_score = 10
        end
    elseif repeat_flag==2  then
        if call_score>9 then
            call_score = 9
        end
    elseif repeat_flag==2  then
        if call_score>10 then
            call_score = 10
        end
    end

    --最后的检测
    if check_is_repeat_score(call_score, call_score_t) then
        --log.error("check_is_repeat_score true!")
        call_score = 0
    end

    log.debug("get_call_score_value:", " tid="..(seat_info.tid or "nil")
        .."| user_id="..(seat_info.m_userid or "nil").."| seat_id="..(seat_info.m_seatid or "nil")
        ..("| pos="..pos).."| call_score="..(call_score or "nil").."|"
        ..(config_index or "nil").."|"..(all_color_score or "nil").."|"..( score_t[1].color or "nil")
    )
    return call_score, config_index, all_color_score, score_t[1].color
end

--============================= Api =============================--
--根据手牌得到 1.叫分 2.调用的数值表编号 3.手牌总得分
function M.calc_handcards_socre(handcards, pos, call_score_t, seat_info, platid)    
    if not handcards
    or not pos
    or not call_score_t
    or not seat_info
    or not next(seat_info) then 
        log.error("calc_handcards_socre error! ", "pos="..(pos or "nil").." |handcards="..serpent.block(handcards or {})
            .." |call_score_t="..serpent.block(call_score_t or {}).." |seat_info="..serpent.block(seat_info or {}))
        return 
    end 

    local score_t = calc_main_color(handcards, platid)
    reset_card_score(score_t)

    return get_call_score_value(score_t, pos, call_score_t, seat_info)
end



return M

